﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.SqlTypes;
using System.Security.Permissions;
using System.Text;

namespace SharpSoft.Data
{
    /// <summary>
    /// 代表一个用于与数据库交互的数据类型
    /// </summary>
    public class SqlValue : INullable
    {
        /// <summary>
        /// 使用一个数据创建<see cref="SqlValue"/>的实例
        /// </summary>
        /// <param name="data">如果该数据类型实现了<see cref="INullable"/>，则使用其实际数据。</param>
        public SqlValue(object data)
        {
            if (data is SqlValue sqlvalue)
            {
                this.value = sqlvalue.value;
            }
            else if (data is INullable nullabledata)
            {
                if (nullabledata.IsNull)
                {
                    this.value = DBNull.Value;
                }
                else
                {
                    var valueProp = data.GetType().GetProperty("Value", System.Reflection.BindingFlags.Public| System.Reflection.BindingFlags.Instance);
                    if (valueProp != null)
                    {
                        this.value = valueProp.GetValue(nullabledata);
                    }
                    else
                    {
                        throw new Exception($"[{data.GetType().FullName}]中没有属性“Value”。");
                    }
                }

            }
            else
            {
                this.value = data;
            }

        }

        private object value;

        public bool IsNull => value == null || value == DBNull.Value;

        /// <summary>
        /// 转换成对应的数据库数据类型
        /// </summary>
        /// <returns></returns>
        public object ToSqlValue()
        {
            if (IsNull)
            {
                return DBNull.Value;
            }
            if (value is string str)
            {
                return new SqlString(str);
            }
            else if (value is bool boo)
            {
                return new SqlBoolean(boo);
            }
            else if (value is byte byt)
            {
                return new SqlByte(byt);
            }
            else if (value is Int16 int16)
            {
                return new SqlInt16(int16);
            }
            else if (value is Int32 int32)
            {
                return new SqlInt32(int32);
            }
            else if (value is Int64 int64)
            {
                return new SqlInt64(int64);
            }
            else if (value is DateTime dt)
            {
                return new SqlDateTime(dt);
            }
            else if (value is Single sing)
            {
                return new SqlSingle(sing);
            }
            else if (value is Double doub)
            {
                return new SqlDouble(doub);
            }
            else if (value is Decimal deci)
            {
                return new SqlDecimal(deci);
            }
            else if (value is Money money)
            {
                return new SqlMoney(money.ToDecimal());
            }
            else if (value is Guid guid)
            {
                return new SqlGuid(guid);
            }
            else if (value is byte[] bs)
            {
                return new SqlBinary(bs);
            }
            else
            {
                return new SqlString(value.ToString());
            }

        }
        /// <summary>
        /// 获取其值在TSQL中的表达形式
        /// </summary>
        /// <returns></returns>
        public string ToTSqlText()
        {
            return SqlUtility.ConvertToTSqlText(value);

        }

        public override string ToString()
        {
            return this.ToTSqlText();
        }
        /// <summary>
        /// 判断对象是否是数据库数据类型
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsSqlDbType(object value)
        {
            if (value == DBNull.Value)
            {
                return true;
            }
            if (value is SqlValue)
            {
                return true;
            }

            if (value is System.Data.SqlTypes.INullable)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
